<?php

namespace beObject\Primitive;

use beObject\Object;
use beObject\Primitive\Boolean;
use beObject\Exceptions\ArithmeticException;
use beObject\Exceptions\IllegalArgumentException;
use beObject\Exceptions\NumberFormatException;

/**
 * Object used to represent an integer.
 * @author Dany Mottier
 * @copyright MD Consult
 * @license http://www.gnu.org/licenses/gpl.html
 * @link http://www.beobject-framework.net/beobject/primary/integer/integer-class/<br />
 * @package beObject\Primitive
 * @version 3.0
 */
class Integer
    extends Object {

  /** @var integer A constant holding the maximum value an int can have, 2^31-1. */
  const __MAX_VALUE = 2147483647;

  /** @var A constant holding the minimum value an int can have, -2^31. */
  const __MIN_VALUE = -2147483647;

  /** @var int */
  private $integer;

  /**
   * Instantiate an integer object with the given value.
   * @param type $integer The integer value to work on.
   * @throws ArithmeticException if the value exceeds the ranges of an integer.
   * @throws IllegalArgumentException if the parameter is not an integer.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-__construct/
   */
  public function __construct($integer) {
    if (is_int($integer)) {
      if ($integer >= self::__MIN_VALUE && $integer <= self::__MAX_VALUE) {
        $this->integer = intval($integer);
      } else {
        throw new ArithmeticException("integer value is out of range");
      }
    } else {
      throw new IllegalArgumentException("first parameter should be an integer");
    }
  }

  /**
   * This magic method is called when the current object is called like a
   * method.
   * @return integer The integer value.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-__invoke/
   */
  public function __invoke() {
    return $this->integer;
  }

  /**
   * Returns the inner property value.
   * @return integer The integer value.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-integerValue/
   */
  public function integerValue() {
    return $this->integer;
  }

  /**
   * Increment the internal integer value.
   * @param Integer $step The step for the incrementation, default is 1.
   * @return Integer The new integer object incremented.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-increment/
   */
  public function increment(Integer $step = null) {
    if (is_null($step)) {
      $step = new Integer(1);
    }
    $this->integer += $step->integerValue();

    return $this;
  }

  /**
   * Returns the string representation implicitly.
   * @return string The string representation of the inner integer value.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-tostring/
   */
  public function toString() {
    return strval($this->integer);
  }

  /**
   * This magic method is called when you output the variable with 'print' or 'echo'.
   * @return string The string representation of the inner integer value.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-__tostring/
   */
  public function __toString() {
    return strval($this->integer);
  }

  /**
   * Parse any variable to an Integer.<br />
   * NB : The unmanaged types will return 0.
   * @param mixed $variable The variable to parse.
   * @return Integer The integer representation of the variable.
   * @link http://www.beobject-framework.net/beobject/primary/integer/integer-parseint/
   */
  public static function parseInt($variable) {
    switch (gettype($variable)) {
      case "boolean" :
        return new Integer($variable === true ? 1 : 0);
      case "integer" :
        return new Integer($variable);
      case "string" :
        return new Integer(intval($variable));
      default :
        if (is_object($variable)) {
          switch (get_class($variable)) {
            case "beObject\Primitive\Boolean" :
              return Integer::parseInt($variable->toInt());
            case "beObject\Primitive\Integer" :
              return $variable;
            case "beObject\Primitive\String" :
              return new Integer(intval($variable->toString()));
            default :
              return new Integer(0);
          }
        } else {
          return new Integer(0);
        }
    }
  }

}

?>
